/*
 * @(#)PatientTransformer.java
 * Date 2013-08-15
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.pix.transformer;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import javax.xml.bind.JAXBElement;

import org.apache.commons.lang3.StringUtils;

import org.hl7.v3.PRPAMT201301UV02Patient;
import org.hl7.v3.PRPAMT201301UV02Person;

import us.hornerscorners.lamppost.config.ModelConfig;

import us.hornerscorners.lamppost.exception.ServiceActionException;

import us.hornerscorners.lamppost.hl7v3common.utils.HL7Utils;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;

import us.hornerscorners.lamppost.model.common.CodedElement;

import us.hornerscorners.lamppost.model.patient.Patient;

import us.hornerscorners.lamppost.transformer.AbstractTransformer;

import us.hornerscorners.lamppost.utils.UTCDateUtils;


/**
 *
 * @author jim
 */
@ApplicationScoped
public class PatientTransformer
        extends AbstractTransformer<PRPAMT201301UV02Patient, Patient> {

    /** Field description */
    @Inject
    private BirthPlaceTransformer birthPlaceTransformer;

    /** Field description */
    @Inject
    private CitizenshipTransformer citizenshipTransformer;

    /** Field description */
    @Inject
    private CodedElementTransformer codedElementTransformer;

    /** Field description */
    @Inject
    private ContactOrganizationTransformer contactOrganizationTransformer;

    /** Field description */
    @Inject
    private EmploymentTransformer employmentTransformer;

    /** Field description */
    @Inject
    private IHEConfig iheConfig;

    /** Field description */
    @Inject
    private InstanceIdentifierTransformer instanceIdentifierTransformer;

    /** Field description */
    @Inject
    private OtherIdentifierTransformer otherIdentifierTransformer;

    /** Field description */
    @Inject
    private PersonNameTransformer personNameTransformer;

    /** Field description */
    @Inject
    private PersonalRelationshipTransformer personalRelationshipTransformer;

    /** Field description */
    @Inject
    private PhoneNumberTransformer phoneNumberTransformer;

    /** Field description */
    @Inject
    private PostalAddressTransformer postalAddressTransformer;

    /**
     * Constructs ...
     *
     */
    public PatientTransformer() {
        super();
    }

    /**
     * Method description
     *
     *
     *
     */

    /**
     * Method description
     *
     *
     * @param jaxbPerson
     *
     */
    private Patient parsePerson(JAXBElement<PRPAMT201301UV02Person> jaxbPerson)
            throws ServiceActionException {

        Patient result = null;

        if (jaxbPerson != null) {

            result = parsePerson(jaxbPerson.getValue());
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param prpaPerson
     *
     */
    private Patient parsePerson(PRPAMT201301UV02Person prpaPerson)
            throws ServiceActionException {

        Patient result = new Patient();

        result.setBirthDate(HL7Utils.parseUTCDate(prpaPerson.getBirthTime(),
                UTCDateUtils.DATE_FORMATS));

        result.setBirthPlace(
            this.birthPlaceTransformer.transform(prpaPerson.getBirthPlace()));

        result.getCitizenships().addAll(
            this.citizenshipTransformer.transform(prpaPerson.getAsCitizen()));

        result.setDeceasedDate(HL7Utils.parseUTCDate(prpaPerson.getDeceasedTime(),
                UTCDateUtils.DATE_FORMATS));
        result.setDeceasedInd(HL7Utils.toBoolean(prpaPerson.getDeceasedInd()));

        result.getEmployments().addAll(
            this.employmentTransformer.transform(prpaPerson.getAsEmployee()));

        result.getEthnicGroups().addAll(
            this.codedElementTransformer.transform(prpaPerson.getEthnicGroupCode()));

        result.setGender(
            this.codedElementTransformer.transform(
                prpaPerson.getAdministrativeGenderCode()));

        // TODO implement this
        // result.getLanguagesSpoken().addAll(prpaPerson.getLanguageCommunication());

        result.setMaritalStatusCode(
            this.codedElementTransformer.transform(prpaPerson.getMaritalStatusCode()));

        result.setMultipleBirthInd(HL7Utils.toBoolean(prpaPerson.getMultipleBirthInd()));
        result.setMultipleBirthOrderNumber(
            HL7Utils.toInteger(prpaPerson.getMultipleBirthOrderNumber()));

        result.getOtherIds().addAll(
            this.otherIdentifierTransformer.transform(prpaPerson.getAsOtherIDs()));

        result.getPersonNames().addAll(
            this.personNameTransformer.transform(prpaPerson.getName()));

        result.getPersonalRelationships().addAll(
            this.personalRelationshipTransformer.transform(
                prpaPerson.getPersonalRelationship()));

        result.getPhoneNumbers().addAll(
            this.phoneNumberTransformer.transform(prpaPerson.getTelecom()));

        result.getPostalAddresses().addAll(
            this.postalAddressTransformer.transform(prpaPerson.getAddr()));

        result.getRaceCodes().addAll(
            this.codedElementTransformer.transform(prpaPerson.getRaceCode()));

        result.setReligiousAffiliationCode(
            this.codedElementTransformer.transform(
                prpaPerson.getReligiousAffiliationCode()));

        return result;
    }

    /**
     * Method description
     *
     *
     * @param prpaPatient
     *
     * @return
     * @throws us.hornerscorners.lamppost.exception.ServiceActionException
     */
    @Override
    public Patient transform(PRPAMT201301UV02Patient prpaPatient)
            throws ServiceActionException {

        Patient result = parsePerson(prpaPatient.getPatientPerson());

        ModelConfig modelConfig = this.iheConfig.getModelConfig();

        CodedElement statusCode =
            this.codedElementTransformer.transform(prpaPatient.getStatusCode());

        if ((statusCode != null) && StringUtils.isBlank(statusCode.getCodeSystem())) {

            statusCode.setCodeSystem(modelConfig.getStatusCodeSystem());
        }

        result.setStatusCode(statusCode);

        result.getIdentifiers().addAll(
            this.instanceIdentifierTransformer.transform(prpaPatient.getId()));

        result.setProviderOrganization(
            this.contactOrganizationTransformer.transform(
                prpaPatient.getProviderOrganization()));

        return result;
    }
}
